#
# LuckyBot4, a python IRC bot
# (c) Copyright 2008 by Lucas van Dijk
# http://www.return1.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
#
# $Id: __init__.py 64 2009-04-27 22:40:55Z luckyluke56 $
#

try:
	from xml.etree import ElementTree
except ImportError:
	try:
		from elementtree import ElementTree
	except ImportError:
		raise

from luckybot import path
from luckybot.bot.plugins import Plugin
from luckybot.luckynet.protocols.irc import Format
import urllib2 as urllib
from datetime import datetime, timedelta
from dateutil.parser import parse
import string

class Twitter(object):
	"""
		Main class for the twitter API
	"""

	user_timeline_url = "http://twitter.com/statuses/user_timeline/%s.xml"

	def _get_xml(self, url):
		"""
			Gets an Element object for the given URL

			@type url: string
			@param url: The url to fetch data from

			@rtype: elementtree.Element
			@return: An Element object
		"""

		data = urllib.urlopen(url)

		try:
			tree = ElementTree.ElementTree(file=data)
		finally:
			data.close()

		if not tree or tree == None:
			raise Exception, 'Could not parse XML'

		return tree.getroot()

	def get_user_timeline(self, username, max = 1):
		"""
			Gets the latest statusses
		"""

		xml = self._get_xml(self.user_timeline_url % username)

		error = xml.find('error')
		if error:
			print error
			raise Exception, error

		statusses = xml.findall('status')

		self.statusses = []

		for status in statusses:
			status_info = {
				'date': parse(status.find('created_at').text),
				'id': int(status.find('id').text),
				'text': status.find('text').text,
				'source': status.find('source').text,
				'user': {
					'id': int(status.find('user').find('id').text),
					'name': status.find('user').find('name').text,
					'screen_name': status.find('user').find('screen_name').text,
					'url': "http://twitter.com/%s" % status.find('user').find('screen_name').text
				}
			}

			self.statusses.append(status_info)

			if len(self.statusses) >= max:
				break

		return self.statusses

class TwitterPlugin(Plugin):
	"""
		Twitter Plugin, shows last twitter messages
	"""

	PLUGIN_INFO = {
		'name': 'Twitter',
		'description': 'Shows latest twitter messages',
		'authors': ['Lucas van Dijk'],
		'version': '1.0',
		'website': 'http://www.return1.net'
	}

	def initialize(self):
		self.notifiers = []

		self.register_command('twitter', self.show_twitter, help=self.lang.get('twitter_help'), args="username")
		self.register_command('twit', self.show_twitter, help=self.lang.get('twitter_help'), args="username")
		self.register_command('twit_notify', self.set_notify, help=self.lang.get('notify_help'), args="username [minutes]")
		self.register_command('twit_unnotify', self.unnotify, help=self.lang.get('unnotify_help'), args="username")

		self.register_message_handler(self.on_message)

	def show_twitter(self, event):
		"""
			Called when twitter command is used
		"""

		if len(event.message.bot_args) == 0:
			event.user.send_notice(self.lang.get('twitter_syntax'))
			return

		twitter = Twitter()
		try:
			messages = twitter.get_user_timeline(event.message.bot_args)
		except Exception, e:
			print e
			event.channel.send_pm(self.lang.get('user_not_found'))
		else:
			self.show_twitter_message(event, messages[0])

	def show_twitter_message(self, event, message):
		"""
			Sends a twitter message to the channel
		"""

		# setup string template
		template = string.Template('${c}${b}[ Twitter:${n} ${name} | ${date}]${c} ${text}')
		result = template.safe_substitute({
			'c': Format.color('darkblue'),
			'b': Format.bold(),
			'n': Format.normal(),
			'name': message['user']['name'],
			'date': message['date'].strftime('%d %b %Y %H:%M:%S '),
			'text': message['text']
		})

		event.channel.send_pm(result)

	def set_notify(self, event):
		"""
			Sets a twitter notifier for this channel
		"""

		args = event.message.bot_args.split()
		if len(args) == 0:
			event.user.send_notice(self.lang.get('notify_syntax').replace('!', self.bot.settings.get('Bot', 'command_prefix')))
			return

		if len(args) == 2:
			minutes = args[1]
		else:
			minutes = 10

		try:
			minutes = int(minutes)
		except:
			event.user.send_notice(self.lang.get('minutes_must_be_number'))
			return

		minutes = max(5, minutes)

		self.notifiers.append({
			'username': args[0],
			'last_check': datetime.now(),
			'last_message': '',
			'minutes': minutes,
			'event': event
		})

		event.channel.send_pm(self.lang.get('notifier_set'))

	def unnotify(self, event):
		"""
			Remove a twitter notifier
		"""

		if not event.message.bot_args:
			event.user.send_notice(self.lang.get('unnotify_syntax').replace('!', self.bot.settings.get('Bot', 'command_prefix')))
			return

		if not event.message.bot_args in self.notifiers:
			event.user.send_notice(self.lang.get('notifier_not_found'))
			return

		if str(self.notifiers[event.message.bot_args]['event'].user) != str(event.user):
			event.user.send_notice(self.lang.get('you_did_not_set_this'))
			return

		self.remove_user(event.message.bot_args)
		event.channel.send_pm(self.lang.get('notifier_deleted'))

	def remove_user(self, nickname):
		"""
			Remove a user from the notifier list
		"""

		indexes = []
		for i, notifier in enumerate(self.notifier):
			if nickname == notifier['username']:
				indexes.append(i)

		if indexes:
			for index in indexes:
				del self.notifiers[index]
			return True

		return False

	def on_message(self, message):
		"""
			Called on each server message
		"""

		to_remove = []

		if self.notifiers:
			for notifier in self.notifiers:
				if notifier['last_check'] + timedelta(minutes=notifier['minutes']) < datetime.now():
					# Ok check for new message
					twitter = Twitter()

					try:
						last_message = twitter.get_user_timeline(notifier['username'])[0]
					except:
						to_remove.append(user)
						continue

					if last_message['text'] != notifier['last_message']:
						self.show_twitter_message(notifier['event'], last_message)

						notifier['last_check'] = datetime.now()
						notifier['last_message'] = last_message['text']

		if to_remove:
			for nick in to_remove:
				self.remove_user(nick)

